package win.larry.util;

import java.io.IOException;
import java.util.Map;

import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

public class HttpClientUtil {
	// 创建连接池管理器
	private static final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
	static {

	}

	public static PoolingHttpClientConnectionManager getSinglePoolingHttpClientConnectionManager() {
		// 设置最大连接数
		cm.setMaxTotal(200);
		// 设置每个主机地址的并发数
		cm.setDefaultMaxPerRoute(3);

		// new IdleConnectionEvictor(cm).start(); // auto-close

		return cm;
	}

	/**
	 * httpClient自己已经集成该类！所以不再需要自定义了。
	 * 
	 * @author Administrator
	 *
	 */
	public static class IdleConnectionEvictor extends Thread {

		private final HttpClientConnectionManager connMgr;

		private volatile boolean shutdown;

		public IdleConnectionEvictor(HttpClientConnectionManager connMgr) {
			this.connMgr = connMgr;
		}

		@Override
		public void run() {
			try {
				while (!this.shutdown) {
					synchronized (this) {
						this.wait(5000);
						// 关闭失效的连接
						this.connMgr.closeExpiredConnections();
					}
				}
			} catch (InterruptedException ex) {
				// 结束
			}
		}

		// 关闭清理无效连接线程
		public void shutdown() {
			this.shutdown = true;
			synchronized (this) {
				this.notifyAll();
			}
		}
	}

	/**
	 * 设置代理。
	 * 
	 * @param httpClient
	 * @param proxy
	 *            格式，"58.56.172.99:80"
	 */
	public static HttpHost prepareProxy(String proxyString) {
		proxyString = proxyString.trim();
		if (proxyString == null) {
			return null;
		}
		String[] ss = proxyString.split(":");
		if (ss == null || ss.length != 2) { // illegal string
			return null;
		}
		return new HttpHost(ss[0], Integer.valueOf(ss[1]));
	}

	/**
	 * 设置要访问的目标地址。仅限于http和https的协议，默认80端口--其他端口无效。
	 * 
	 * @param targetUrl
	 * @return
	 */
	public static HttpHost prepareTarget(String targetUrl) {
		targetUrl = targetUrl.trim().toLowerCase();
		if (targetUrl == null) {
			return null;
		}
		String protocol = "http";
		String url = "";
		int port = -1; // 默认就80了，一个电商网站，不应该还有8080这种端口
		if (targetUrl.contains(":")) {
			protocol = targetUrl.substring(0, targetUrl.indexOf(":"));
			url = targetUrl.substring(targetUrl.indexOf(":") + 1).replace("//", "");
		} else {
			url = targetUrl;
		}
		return new HttpHost(url, port, protocol);
	}

	/**
	 * 
	 * @param request
	 */
	public static void setHeaders(HttpRequestBase request) {
		request.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
		request.addHeader("Accept-Encoding", "gzip, deflate, sdch");
		request.addHeader("Accept-Language", "zh-CN,zh;q=0.8");
		// request.addHeader("Connection", "keep-alive");
		request.addHeader("Connection", "close ");
		request.addHeader("Host", "www.baidu.com");
		request.addHeader("Upgrade-Insecure-Requests", "1");
		request.addHeader("User-Agent",
				"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36");
	}

	/**
	 * 
	 * @param targetUrl
	 * @param proxyString
	 * @return
	 * 		返回响应码
	 * @throws Exception
	 */
	public static int doGet(String targetUrl, String proxyString) throws Exception {

		// long time0 = System.currentTimeMillis();
		HttpHost proxy = HttpClientUtil.prepareProxy(proxyString);
		HttpHost target = HttpClientUtil.prepareTarget(targetUrl);
		if (proxy == null || target == null) {
			return -1;
		}
		CloseableHttpClient httpclient = HttpClients
				.custom()/*
							 * .setConnectionManager(HttpClientUtil.
							 * getSinglePoolingHttpClientConnectionManager())
							 */
				.setRetryHandler(new DefaultHttpRequestRetryHandler()).evictExpiredConnections().setProxy(proxy).build();

		RequestConfig config = RequestConfig.custom()/* .setProxy(proxy) */.setConnectTimeout(2000).setConnectionRequestTimeout(2000).build();

		HttpGet request = new HttpGet("/");
		request.setConfig(config);
		HttpClientUtil.setHeaders(request);

		// System.out.println("----------------------------------------");
		// System.out.println("Executing request " +
		// request.getRequestLine() + " to " + target + " via " + proxy);

		// CloseableHttpResponse response = null;
		try (CloseableHttpResponse response = httpclient.execute(target, request);) {
			// response = httpclient.execute(target, request);

			System.out.println("Executing request " + request.getRequestLine() + " to " + target + " via " + proxy + "\r\nresponse status line: "
					+ response.getStatusLine().getStatusCode());
			return response.getStatusLine().getStatusCode();
		} finally {
			// if (response != null) {
			// response.close();
			// }
			// 此处不能关闭httpClient，如果关闭httpClient，连接池也会销毁
			httpclient.close();
		}

	}

	/**
	 * 
	 * @param targetUrl
	 * @param proxyString
	 * @throws Exception
	 */
	public static void doGet2(String targetUrl, String proxyString, Map<String, String> map) {

		// long time0 = System.currentTimeMillis();
		HttpHost proxy = HttpClientUtil.prepareProxy(proxyString);
		String target = targetUrl.trim();
		if (proxy == null || target == null || target.isEmpty()) {
			return;
		}
		CloseableHttpClient httpclient = HttpClients.custom().setRetryHandler(new DefaultHttpRequestRetryHandler()).evictExpiredConnections()
				.setProxy(proxy).build();

		RequestConfig config = RequestConfig.custom()/* .setProxy(proxy) */.setConnectTimeout(2000).setConnectionRequestTimeout(2000).build();

		HttpGet request = new HttpGet(target);
		request.setConfig(config);
		HttpClientUtil.setHeaders(request);

		// CloseableHttpResponse response = null;
		try (CloseableHttpResponse response = httpclient.execute(request);) {
			// response = httpclient.execute(target, request);
			int statusCode = response.getStatusLine().getStatusCode();
			System.out.println(
					"Executing request " + request.getRequestLine() + " to " + target + " via " + proxy + "\r\nresponse status line: " + statusCode);
			if (statusCode != -1) {
				map.put(proxyString, statusCode + "");
			}
		} catch (ClientProtocolException e) {
			// e.printStackTrace();
			System.out.println("协议错误！");
		} catch (IOException e) {
			// e.printStackTrace();
			System.out.println("连接超时！");
		} finally {
			// if (response != null) {
			// response.close();
			// }
			// 此处不能关闭httpClient，如果关闭httpClient，连接池也会销毁
			try {
				httpclient.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}
}
